package com.yc.damai.web;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yc.damai.bean.SecondKill;
import com.yc.damai.bean.SecondKillItem;
import com.yc.damai.entity.DmOrderitem;
import com.yc.damai.entity.DmOrders;
import com.yc.damai.entity.DmProduct;
import com.yc.damai.entity.DmUser;
import com.yc.damai.mapper.DmOrderitemMapper;
import com.yc.damai.mapper.DmOrdersMapper;
import com.yc.damai.mapper.DmProductMapper;
import com.yc.login.vo.Result;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/*
* 秒杀:在某个时间点开始对某类商品进行促销的活动,秒杀有时间限制.

1. 商户设置秒杀(大促)活动
	1) 开始时间,结束时间,价格策略...
	2) 参与商品的集合
	1对多关系

2. 一旦生成秒杀的数据, 那么产生定时任务
3. 到达活动开始的时间, 自动启动任务
4. 查询出参与活动的商品, 保存到redis中
5. 数据库中减去参与秒杀的商品的数量
6. 响应用户请求, 生成秒杀订单(单独的订单方法)
     redis + rabbitMQ
7. 秒杀结束, 将秒杀剩余的商品数量加入数据库
*
* */

@RestController
public class SecondKillDo {

    // 当前秒杀活动的对象, TODO 扩展: 保存在 Redis
    private SecondKill currentSecondKill;

    @Resource
    // 查询商品 TODO 远程调用 other 查询
    private DmProductMapper productMapper;

    @Resource
    private TaskScheduler taskScheduler;

    // 使用定时任务, 启动秒杀 TODO 参考 SpringBoot 定时任务
    @RequestMapping("nextSecondKill")
    public SecondKill nextSecondKill(){

        if(currentSecondKill != null){
            // 秒杀已经开始
            return currentSecondKill;
        }

        // 直接构建, TODO 查询数据库的记录 远程调用 ohter
        SecondKill sk = new SecondKill();
        //LocalDateTime startTime = LocalDateTime.of(2024, 5, 17, 20, 0, 0);
                    LocalDateTime startTime = LocalDateTime.now().plusSeconds(10);
            sk.setStartTime(startTime);
            LocalDateTime finishTime = startTime.plusSeconds(600);
            sk.setFinishTime(finishTime);
            sk.setRate(0.8);
            // 查询商品: 查询库存最多的 10 个商品
            IPage<DmProduct> page = new Page<>(1,10);
            page.orders().add(OrderItem.desc("store"));
            IPage<DmProduct> iPage = productMapper.selectPage(page, null);
            // 将 List<Product> 转成 List<SecondKillItem>
            sk.setProducts(iPage.getRecords().stream().map(product->{
                SecondKillItem secondKillItem = new SecondKillItem();
                secondKillItem.setProduct(product);
                // 计算折扣价
                secondKillItem.setPrice(product.getShopPrice() * sk.getRate());
            return secondKillItem;
        }).collect(Collectors.toList()));

        currentSecondKill = sk;

        // 扣减库存
        for (SecondKillItem secondKillItem : sk.getProducts()) {
            // 扣减库存100
            secondKillItem.getProduct().setStore(
                    secondKillItem.getProduct().getStore() - 100);
            productMapper.updateById(secondKillItem.getProduct());
            // 设置秒杀数量 100
            secondKillItem.getProduct().setStore(100);
        }

//        currentSecondKill.getFinishTime().
        //Date finishDate = new Date(System.currentTimeMillis() + 1000*60*3);

        // 根据时区获取 秒值
        long time = currentSecondKill.getFinishTime().toEpochSecond(ZoneOffset.ofHours(8));
        // 讲秒值转为毫秒值
        Date finishDate = new Date(time * 1000);
        System.out.println("========== 秒杀活动将在 "+finishDate+" 结束 ================");
        // 开启延时任务 : 秒杀活动终止
        taskScheduler.schedule(()->{
            finish();
        }, finishDate);

        return currentSecondKill;

    }

//    public static void main(String[] args) {
//        System.out.println("LocalDateTime.now() = " + LocalDateTime.now());
//        long time = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8));
//        Date finishDate = new Date(time*1000);
//        System.out.println("finishDate = " + finishDate);
//    }

    private void finish(){
        // 将秒杀剩余的商品数量加入数据库
        for (SecondKillItem secondKillItem : currentSecondKill.getProducts()) {
            DmProduct dbProduct = productMapper.selectById(secondKillItem.getProduct().getId());
            dbProduct.setStore(dbProduct.getStore() + secondKillItem.getProduct().getStore());
            productMapper.updateById(dbProduct);
        }

        // currentSecondKill 置空
        currentSecondKill = null;
        System.out.println("=========== 秒杀活动结束 ===========");
    }

    // 假定每次秒杀只能, 秒杀一个商品 TODO 秒杀购物车
    @RequestMapping("secondKill")
    public synchronized Result secondKill(@SessionAttribute(required = false) DmUser loginedUser,
                             int pid) {
        if (currentSecondKill == null ||
                currentSecondKill.getStartTime().isBefore(LocalDateTime.now()) == false) {
            return new Result(-1, "秒杀活动未开始!", null);
        }
        if (loginedUser == null) {
            return new Result(0, "请先登录系统!", null);
        }

        // TODO Redis 中完成下列操作
        List<SecondKillItem> list = currentSecondKill.getProducts()
                .stream()
                .filter(ski -> ski.getProduct().getId() == pid)
                .collect(Collectors.toList());
        if (list.isEmpty()) {
            return new Result(-2, "该商品未参与秒杀!", null);
        }
        DmProduct product = list.get(0).getProduct();
        if (product.getStore() == 0) {
            return new Result(-3, "该商品已卖完!", null);
        }
        product.setStore(product.getStore() - 1);

        // TODO 未完待续...
        DmOrders order = new DmOrders();
        order.setUid(loginedUser.getId());
        DmOrderitem item = new DmOrderitem();
        item.setPid(pid);
        order.setItems(new ArrayList<>());
        order.getItems().add(item);
        rabbitTemplate.convertAndSend("skQueue", order);
        // 向消息队列发送订单消息, 同 消息队列 将 uid 和 pid 发送给 秒杀订单方法
        System.out.println("向消息队列发送订单消息, 同 消息队列 将 uid 和 pid 发送给 秒杀订单方法");

        return new Result(1,"秒杀成功!",null);
    }

    @Resource
    RabbitTemplate rabbitTemplate;
//    @Resource
//    DmOrdersMapper ordersMapper;
//    @Resource
//    DmOrderitemMapper orderitemMapper;
//
//    // TODO 秒杀订单的方法 , 定义在 other 中, 通过 消息队列 + 调用other方法方式执行
//    @Transactional
//    @RabbitListener(queuesToDeclare = @Queue("skQueue"))
//    public void secondKillOrder(DmOrders order){
//        // aid 收货地址
//        // 与普通的区别, 少了扣减库存的操作
//
//        Integer pid = order.getItems().get(0).getPid();
//        DmProduct dmProduct = productMapper.selectById(pid);
//
//        order.setTotal(dmProduct.getShopPrice());
//        order.setAid(order.getAid());
//        order.setState(1);
//        order.setCreatetime(LocalDateTime.now());
//        ordersMapper.insert(order);
//        for (DmOrderitem item : order.getItems()) {
//            item.setOid(order.getId());
//            item.setCount(1);
//            item.setTotal(dmProduct.getShopPrice());
//            orderitemMapper.insert(item);
//        }
//        System.out.println("秒杀订单完成");
//    }

    @RequestMapping("querySKProduct")
    public SecondKill querySKProduct(){
        if(currentSecondKill.getStartTime().isBefore(LocalDateTime.now()) == false){
            return null;
        }
        return currentSecondKill;
    }


}
